﻿/*
 * timestamp.hpp
 *
 *  Created on: 2017年1月3日
 *      Author: work
 */

#ifndef _DM_TIMESTAMP_HPP_
#define _DM_TIMESTAMP_HPP_

#include <dm/export.hpp>

#ifndef DM_API_MISC
#define DM_API_MISC DM_API_IMPORT
#endif

#include <ctime>
#include <dm/types.hpp>

namespace dm{

class DM_API_MISC CTimeStamp{
public:
	typedef std::time_t s_t;
	typedef uint32 us_t;

	CTimeStamp():m_s(0),m_us(0){}
	CTimeStamp( s_t s,us_t us ):m_s(s),m_us(us){}
	CTimeStamp( const CTimeStamp& ts ):m_s(ts.m_s),m_us(ts.m_us){}
	CTimeStamp( const volatile CTimeStamp& ts ):m_s(ts.m_s),m_us(ts.m_us){}

	static CTimeStamp cur();

	inline bool isInv()const{
		return m_s==0 && m_us==0;
	}

	inline bool isInv()const volatile{
		return m_s==0 && m_us==0;
	}

	inline CTimeStamp& operator=( const CTimeStamp& ts ){
		m_s = ts.m_s;
		m_us = ts.m_us;
		return *this;
	}

	inline volatile CTimeStamp& operator=( const CTimeStamp& ts )volatile{
		m_s = ts.m_s;
		m_us = ts.m_us;
		return *this;
	}

	inline CTimeStamp& operator=( volatile const CTimeStamp& ts ){
		m_s = ts.m_s;
		m_us = ts.m_us;
		return *this;
	}

	inline volatile CTimeStamp& operator=( volatile const CTimeStamp& ts )volatile{
		m_s = ts.m_s;
		m_us = ts.m_us;
		return *this;
	}

	inline bool operator==( const CTimeStamp& ts )const{
		return m_s==ts.m_s && m_us==ts.m_us;
	}

	inline bool operator==( volatile const CTimeStamp& ts )const{
		return m_s==ts.m_s && m_us==ts.m_us;
	}

	inline bool operator==( const CTimeStamp& ts )const volatile{
		return m_s==ts.m_s && m_us==ts.m_us;
	}

	inline bool operator==( const volatile CTimeStamp& ts )const volatile{
		return m_s==ts.m_s && m_us==ts.m_us;
	}

	inline bool operator!=( const CTimeStamp& ts )const{
		return m_s!=ts.m_s || m_us!=ts.m_us;
	}

	inline bool operator<( const CTimeStamp& ts )const{
		return m_s<ts.m_s || (m_s==ts.m_s&&m_us<ts.m_us);
	}

	inline bool operator<( const CTimeStamp& ts )const volatile{
		return m_s<ts.m_s || (m_s==ts.m_s&&m_us<ts.m_us);
	}

	inline bool operator>( const CTimeStamp& ts )const{
		return m_s>ts.m_s || ( m_s==ts.m_s && m_us>ts.m_us );
	}

	inline bool operator>( const CTimeStamp& ts )const volatile{
		return m_s>ts.m_s || ( m_s==ts.m_s && m_us>ts.m_us );
	}

	inline bool operator<=( const CTimeStamp& ts )const{
		return m_s<ts.m_s || ( m_s==ts.m_s && m_us<=ts.m_us );
	}

	inline bool operator<=( const CTimeStamp& ts )const volatile{
		return m_s<ts.m_s || ( m_s==ts.m_s && m_us<=ts.m_us );
	}

	inline bool operator>=( const CTimeStamp& ts )const{
		return m_s>ts.m_s || ( m_s==ts.m_s && m_us>=ts.m_us );
	}

	inline bool operator>=( const CTimeStamp& ts )const volatile{
		return m_s>ts.m_s || ( m_s==ts.m_s && m_us>=ts.m_us );
	}

	inline const s_t& seconds()const{
		return m_s;
	}

	inline dm::uint16 mseconds()const{
		return (dm::uint16)(m_us*0.001);
	}

	inline s_t seconds()const volatile{
		return m_s;
	}

	inline dm::uint16 mseconds()const volatile{
		return (dm::uint16)(m_us*0.001);
	}

	inline void setMseconds( const dm::uint16& ms ){
		m_us = (ms%1000);
		m_us *= 1000;
	}

	inline const us_t& useconds()const{
		return m_us;
	}

	inline us_t useconds()const volatile{
		return m_us;
	}

	inline bool isTimeout( s_t seconds,unsigned int usecs,const CTimeStamp& now = cur() )const{
		seconds += m_s;
		return (seconds < now.m_s) || (seconds==now.m_s && usecs<now.m_us);
	}

	inline bool isTimeout( s_t seconds,unsigned int usecs,const CTimeStamp& now = cur() )const volatile{
		seconds += m_s;
		return (seconds < now.m_s) || (seconds==now.m_s && usecs<now.m_us);
	}

	inline bool isTimeout_sec( s_t seconds,const CTimeStamp& now = cur() )const{
		return (m_s + seconds) < now.m_s;
	}

	inline bool isTimeout_sec( s_t seconds,const CTimeStamp& now = cur() )const volatile{
		return (m_s + seconds) < now.m_s;
	}

	inline bool isTimeout_msec( const dm::uint16& ms,const CTimeStamp& now = cur() )const{
		return isTimeout( ms/1000,(ms%1000)*1000l,now);
	}

	inline bool isTimeout_msec( dm::uint16 ms,const CTimeStamp& now = cur() )const volatile{
		return isTimeout( ms/1000,(ms%1000)*1000l,now);
	}

	inline bool isTimeout_usec( const us_t& us,const CTimeStamp& now = cur() )const{
		return isTimeout( us/1000000,us%1000000,now);
	}

	inline bool isTimeout_usec( const us_t& us,const CTimeStamp& now = cur() )const volatile{
		return isTimeout( us/1000000,us%1000000,now);
	}

	// 设置秒
	inline void setSeconds( s_t s ){
		m_s = s;
	}

	// 设置微妙
	inline void setUseconds( us_t us ){
		m_us = (us%1000000);
	}

	inline void addSec( s_t s ){
		m_s += s;
	}

	inline void addSec( s_t s )volatile{
		m_s += s;
	}

    inline void delSec( s_t s ){
        m_s -= s;
    }

	inline void addUs( us_t us ){
		m_us += us;
		m_s += m_us/1000000u;
		m_us %= 1000000u;
	}

	inline void addUs( us_t us )volatile{
		m_us += us;
		m_s += m_us/1000000u;
		m_us %= 1000000u;
	}

	inline void addMs( s_t ms ){
		addSec( ms/1000u );
		addUs( (ms%1000u) * 1000u );
	}

	inline void addMs( s_t ms ) volatile{
		addSec( ms/1000u );
		addUs( (ms%1000u) * 1000u );
	}

	inline void del( s_t s,us_t us ){
		m_s -= s;
		if( m_us<us ){
			us = 1000000-us;
			m_us += us;
			--m_s;
		}else{
			m_us -= us;
		}
		m_us -= us;
	}

	inline void delMSec( s_t ms ){
		del(ms/1000,(ms%1000)*1000);
	}

	inline void delUSec( us_t us ){
		del(us/1000000,us%1000000);
	}

	inline void setInv(){
		m_s = 0;
		m_us = 0;
	}

	inline void setInv()volatile{
		m_s = 0;
		m_us = 0;
	}

	inline s_t escapeSecs( const dm::CTimeStamp& now = dm::CTimeStamp::cur() )const{
		if( now.m_s>m_s )
			return now.m_s - m_s;
		else
			return 0;
	}

	inline s_t escapeMSecs( const dm::CTimeStamp& now = dm::CTimeStamp::cur() )const{
		s_t ms = 0;

		if( now.m_s>m_s ){
			ms = now.m_s - m_s;
			ms = ms*1000 + (now.m_us-m_us)/1000;
		}

		return ms;
	}

	inline s_t escapeUSecs( const dm::CTimeStamp& now = dm::CTimeStamp::cur() )const{
		s_t us = 0;
		if( now.m_s>m_s ){
			us = now.m_s - m_s;
			us = us*1000000 - m_us + now.m_us;
		}

		return us;
	}

	inline void copy( const CTimeStamp& ts ){
		m_s = ts.m_s;
		m_us = ts.m_us;
	}

	inline void copy( const CTimeStamp& ts )volatile{
		m_s = ts.m_s;
		m_us = ts.m_us;
	}

	inline void copy( const volatile CTimeStamp& ts ){
		m_s = ts.m_s;
		m_us = ts.m_us;
	}

	inline void copy( const volatile CTimeStamp& ts )volatile{
		m_s = ts.m_s;
		m_us = ts.m_us;
	}
public:
	s_t 	m_s;	// 秒
	us_t	m_us;	// 微妙
};

}

#endif /* INCLUDE_DM_TIMESTAMP_HPP_ */
